package com.frostwire.mp3;

import java.util.Arrays;

public class ID3v1Tag implements ID3v1 {
    public static final int TAG_LENGTH = 128;
    private static final String VERSION_0 = "0";
    private static final String VERSION_1 = "1";
    private static final String TAG = "TAG";
    private static final int TITLE_OFFSET = 3;
    private static final int TITLE_LENGTH = 30;
    private static final int ARTIST_OFFSET = 33;
    private static final int ARTIST_LENGTH = 30;
    private static final int ALBUM_OFFSET = 63;
    private static final int ALBUM_LENGTH = 30;
    private static final int YEAR_OFFSET = 93;
    private static final int YEAR_LENGTH = 4;
    private static final int COMMENT_OFFSET = 97;
    private static final int COMMENT_LENGTH_V1_0 = 30;
    private static final int COMMENT_LENGTH_V1_1 = 28;
    private static final int TRACK_MARKER_OFFSET = 125;
    private static final int TRACK_OFFSET = 126;
    private static final int GENRE_OFFSET = 127;
    private String track = null;
    private String artist = null;
    private String title = null;
    private String album = null;
    private String year = null;
    private int genre = -1;
    private String comment = null;

    public ID3v1Tag() {
    }

    public ID3v1Tag(byte[] bytes) throws NoSuchTagException {
        unpackTag(bytes);
    }

    private void unpackTag(byte[] bytes) throws NoSuchTagException {
        sanityCheckTag(bytes);
        title = BufferTools.trimStringRight(BufferTools.byteBufferToString(bytes, TITLE_OFFSET, TITLE_LENGTH));
        artist = BufferTools.trimStringRight(BufferTools.byteBufferToString(bytes, ARTIST_OFFSET, ARTIST_LENGTH));
        album = BufferTools.trimStringRight(BufferTools.byteBufferToString(bytes, ALBUM_OFFSET, ALBUM_LENGTH));
        year = BufferTools.trimStringRight(BufferTools.byteBufferToString(bytes, YEAR_OFFSET, YEAR_LENGTH));
        genre = bytes[GENRE_OFFSET] & 0xFF;
        if (genre == 0xFF) {
            genre = -1;
        }
        if (bytes[TRACK_MARKER_OFFSET] != 0) {
            comment = BufferTools.trimStringRight(BufferTools.byteBufferToString(bytes, COMMENT_OFFSET, COMMENT_LENGTH_V1_0));
            track = null;
        } else {
            comment = BufferTools.trimStringRight(BufferTools.byteBufferToString(bytes, COMMENT_OFFSET, COMMENT_LENGTH_V1_1));
            int trackInt = bytes[TRACK_OFFSET];
            if (trackInt == 0) {
                track = "";
            } else {
                track = Integer.toString(trackInt);
            }
        }
    }

    private void sanityCheckTag(byte[] bytes) throws NoSuchTagException {
        if (bytes.length != TAG_LENGTH) {
            throw new NoSuchTagException("Buffer length wrong");
        }
        if (!TAG.equals(BufferTools.byteBufferToString(bytes, 0, TAG.length()))) {
            throw new NoSuchTagException();
        }
    }

    public byte[] toBytes() {
        byte[] bytes = new byte[TAG_LENGTH];
        packTag(bytes);
        return bytes;
    }

    public void toBytes(byte[] bytes) {
        packTag(bytes);
    }

    public void packTag(byte[] bytes) {
        Arrays.fill(bytes, (byte) 0);
        BufferTools.stringIntoByteBuffer(TAG, 0, 3, bytes, 0);
        packField(bytes, title, TITLE_LENGTH, TITLE_OFFSET);
        packField(bytes, artist, ARTIST_LENGTH, ARTIST_OFFSET);
        packField(bytes, album, ALBUM_LENGTH, ALBUM_OFFSET);
        packField(bytes, year, YEAR_LENGTH, YEAR_OFFSET);
        if (genre < 128) {
            bytes[GENRE_OFFSET] = (byte) genre;
        } else {
            bytes[GENRE_OFFSET] = (byte) (genre - 256);
        }
        if (track == null) {
            packField(bytes, comment, COMMENT_LENGTH_V1_0, COMMENT_OFFSET);
        } else {
            packField(bytes, comment, COMMENT_LENGTH_V1_1, COMMENT_OFFSET);
            String trackTemp = numericsOnly(track);
            if (trackTemp.length() > 0) {
                int trackInt = Integer.parseInt(trackTemp);
                if (trackInt < 128) {
                    bytes[TRACK_OFFSET] = (byte) trackInt;
                } else {
                    bytes[TRACK_OFFSET] = (byte) (trackInt - 256);
                }
            }
        }
    }

    private void packField(byte[] bytes, String value, int maxLength, int offset) {
        if (value != null) {
            BufferTools.stringIntoByteBuffer(value, 0, Math.min(value.length(), maxLength), bytes, offset);
        }
    }

    private String numericsOnly(String s) {
        StringBuilder stringBuffer = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (ch >= '0' && ch <= '9') {
                stringBuffer.append(ch);
            } else {
                break;
            }
        }
        return stringBuffer.toString();
    }

    public String getVersion() {
        if (track == null) {
            return VERSION_0;
        } else {
            return VERSION_1;
        }
    }

    public String getTrack() {
        return track;
    }

    public void setTrack(String track) {
        this.track = track;
    }

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAlbum() {
        return album;
    }

    public void setAlbum(String album) {
        this.album = album;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public int getGenre() {
        return genre;
    }

    public void setGenre(int genre) {
        this.genre = genre;
    }

    public String getGenreDescription() {
        try {
            return ID3v1Genres.GENRES[genre];
        } catch (ArrayIndexOutOfBoundsException e) {
            return "Unknown";
        }
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public boolean equals(Object obj) {
        if (!(obj instanceof ID3v1Tag)) return false;
        if (super.equals(obj)) return true;
        ID3v1Tag other = (ID3v1Tag) obj;
        if (genre != other.genre) return false;
        if (track == null) {
            if (other.track != null) return false;
        } else if (other.track == null) return false;
        else if (!track.equals(other.track)) return false;
        if (artist == null) {
            if (other.artist != null) return false;
        } else if (other.artist == null) return false;
        else if (!artist.equals(other.artist)) return false;
        if (title == null) {
            if (other.title != null) return false;
        } else if (other.title == null) return false;
        else if (!title.equals(other.title)) return false;
        if (album == null) {
            if (other.album != null) return false;
        } else if (other.album == null) return false;
        else if (!album.equals(other.album)) return false;
        if (year == null) {
            if (other.year != null) return false;
        } else if (other.year == null) return false;
        else if (!year.equals(other.year)) return false;
        if (comment == null) {
            if (other.comment != null) return false;
        } else if (other.comment == null) return false;
        else if (!comment.equals(other.comment)) return false;
        return true;
    }
}
